﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;

using Pibby.UI;
using Pibby.Core;
using Pibby.Core.IO;
using invrt;
using Pibby.Core.Logging;
using Pibby.Core.Models;
using Pibby.Core.Presenters;
using Pibby.Core.Persistence;
using Pibby.Core.Views;



namespace Pibby
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault(false);

			AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);

			Log.Configure();
			Log.Info(string.Format(Resources.Log_StartingApplicationFormat, Application.ExecutablePath));

			try
			{
				Log.Debug("Initialising IOC");

				InitializeIOC();

				Log.Debug("Searching for paths...");

				var defaultSettingsFolder = new FileSystemFolder(Environment.SpecialFolder.Personal).Append(Application.ProductName);
				var defaultDownloadFolder = new FileSystemFolder(Environment.SpecialFolder.MyMusic).Append("Podcasts");

				var searchPaths = new IFolderCollection();

				searchPaths.Add(new FileSystemFolder(Application.StartupPath));
				searchPaths.Add(defaultSettingsFolder);

				Log.Debug("Searching for settings...");

				IUserSettings settings = LoadSettings(ApplicationDefaults.DefaultSettingsFileName,
																searchPaths,
																defaultSettingsFolder,
																defaultDownloadFolder);

				Log.Debug("Searching for repository...");

				LoadRepository(ApplicationDefaults.DefaultDbFileName,
																settings,
																searchPaths,
																defaultSettingsFolder);

				Log.Debug("Creating model...");

				PodcatcherModel model = new PodcatcherModel(settings, new PodcastRepositoryFactory(settings.RepositoryPath));

				Log.Debug("Creating main form...");

				MainForm mainForm = new MainForm(model);

				Application.Run(mainForm);

				Log.Debug("Application closed.");
			}
			catch (Exception ex)
			{
				Log.Error(ex.Message);
			}
        }

		static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
		{
			Exception ex = e.ExceptionObject as Exception;

			if (ex != null)
				Log.Error(ex.ToString());
			else
				Log.Error("Error of unknown type thrown in applicaton domain");

			Environment.Exit(-1);
		}

		private static void InitializeIOC()
		{
			InversionOfController.Factory = new TypeFactory(new SimpleTypeResolver());

			InversionOfController.Factory.RegisterType<Pibby.Core.Web.IDownloadingService, Pibby.Core.Web.WebDownloadingService>();
			InversionOfController.Factory.RegisterType<IDriveFactory, Pibby.Core.IO.FileSystemDriveFactory>();
			InversionOfController.Factory.RegisterType<IFolderFactory, Pibby.Core.IO.FileSystemFolderFactory>();
			InversionOfController.Factory.RegisterType<ICopyFiles, SimpleFileCopier>();
			InversionOfController.Factory.RegisterType<ITextReaderFactory, TextReaderFactory>();
			InversionOfController.Factory.RegisterType<ITextWriterFactory, TextWriterFactory>();
			InversionOfController.Factory.RegisterType<IEjectDevices, Pibby.Core.IO.PortableMediaEjector>();
			InversionOfController.Factory.RegisterType<IRecycleFiles, Pibby.Core.IO.RecycleBin>();
			InversionOfController.Factory.RegisterType<IProgressIndicator, WindowsSevenProgressIndicator>();
			InversionOfController.Factory.RegisterType<ITaskbarManager, WindowsSevenTaskbarManager>(); 
		}

        public static IUserSettings LoadSettings(string settingsName, IFolderCollection searchPaths, IFolder defaultSettingsPath, IFolder defaultDownloadPath)
		{
			Contract.EnsureIsNotNullOrEmpty(settingsName, "No settings file name");
			Contract.EnsureIsNotNull(searchPaths, "No search paths provided");
			Contract.EnsureIsNotNull(defaultSettingsPath, "No settings path provided");
			Contract.EnsureIsNotNull(defaultDownloadPath, "No download path provided");

			IUserSettings settings;

			try
			{
				settings = ApplicationSettingsFinder.LoadSettings(settingsName, searchPaths, defaultSettingsPath, defaultDownloadPath);
			}
			catch (System.Xml.XmlException ex)
			{
				Pibby.Core.Logging.Log.Error(ex.Message);

				settings = new PerUserSettings();
			}

			return settings;
		}

		public static IPodcastRepository LoadRepository(string repositoryName, IUserSettings settings, IFolderCollection searchPaths, IFolder defaultRepositoryPath)
		{
			Contract.EnsureIsNotNullOrEmpty(repositoryName, "No repository file name");
			Contract.EnsureIsNotNull(settings, "Settings not initialised - Call LoadSettings first");
			Contract.EnsureIsNotNull(defaultRepositoryPath, "No repository path provided");

			IPodcastRepository repository = RepositoryFinder.FindRepository(settings, repositoryName, searchPaths, defaultRepositoryPath);

			if (repository != null)
			{
				ApplicationVersion applicationInstance = new ApplicationVersion(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);

				ApplicationVersion databaseInstance = repository.GetVersion();

				if (databaseInstance == null)
				{
					repository.CreateNewDatabase();
				}
				else
				{
					if (applicationInstance.Version > databaseInstance.Version)
					{
						repository.Update(applicationInstance);
					}
					else if (applicationInstance.Version == databaseInstance.Version)
					{
						// do we need to apply development sql ???
						repository.UpdateDevelopment();
					}
				}
			}

			return repository;
		}

	}
}
